package com.speedchina.oauth2_permission.web.sys.api_v1;

import com.speedchina.common.download.utils.CsvWriter;
import com.speedchina.common.download.utils.ExcelUtils;
import com.speedchina.common.upload.response.Result;
import com.speedchina.common.upload.utils.ExcelCSVReadUtils;
import com.speedchina.common.upload.utils.MapUtil;
import com.speedchina.framework.base.QueryModel;
import com.speedchina.framework.helper.Assert;
import com.speedchina.framework.model.R;
import com.speedchina.framework.validator.ValidatorHelper;
import com.speedchina.framework.validator.group.AddGroup;
import com.speedchina.framework.validator.group.UpdateGroup;
import com.speedchina.oauth2_permission.aspect.SysLog;
import com.speedchina.oauth2_permission.utils.SecurityUtils;
import com.speedchina.permission.base.constant.SysConstant;
import com.speedchina.permission.base.i18n.I18nService;
import com.speedchina.permission.domain.sys.dto.UserDTO;
import com.speedchina.permission.domain.sys.entity.User;
import com.speedchina.permission.domain.sys.po.UserPo;
import com.speedchina.permission.service.sys.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.io.FileInputStream;
import java.io.Serializable;
import java.util.*;

/**
 * 系统-用户表 接口
 *
 * @author hank
 * @date 2021-04-08 13:59:05
 */
@RestController
@RequestMapping("/sys/user")
@Api(description = "系统-用户表 接口")
public class UserController {

    @Autowired
    private I18nService i18nService;

    @Autowired
    private UserService service;

    @ApiOperation("分页查询")
    @GetMapping
    @SysLog("分页查询-系统-用户表")
    //@PreAuthorize("hasAuthority('sys:user:list')")
    public R query(Integer pageNo, Integer pageSize, UserPo params) {
        return R.page(service.queryPage(new QueryModel<>(pageNo, pageSize, params)));
    }

    @ApiOperation("详情查询")
    @GetMapping("/get")
    @SysLog("详情查询-系统-用户表")
    //@PreAuthorize("hasAuthority('sys:user:info')")
    public R get(UserPo params) {
        return R.data(service.get(params));
    }

    @ApiOperation("新增")
    @ApiImplicitParams({
            // @ApiImplicitParam(name = "", value = "", dataType = "String", paramType = "path")
    })
    @PostMapping
    @SysLog("新增-系统-用户表")
    @PreAuthorize("hasAuthority('sys:user:add')")
    public R add(@RequestBody UserPo entity) {
        ValidatorHelper.validateEntity(entity, AddGroup.class);
        return R.data(service.save(entity));
    }

    @ApiOperation("修改")
    @ApiImplicitParams({
            // @ApiImplicitParam(name = "id", value = "主键", dataType = "Long", paramType = "path")
    })
    @PutMapping
    @SysLog("修改-系统-用户表")
    @PreAuthorize("hasAuthority('sys:user:update')")
    public R update(@RequestBody UserPo entity) {
        ValidatorHelper.validateEntity(entity, UpdateGroup.class);
        return R.data(service.update(entity));
    }

    @ApiOperation("批量删除")
    @DeleteMapping("/{ids}")
    @SysLog("批量删除-系统-用户表")
    @PreAuthorize("hasAuthority('sys:user:delete')")
    public R delete(@PathVariable("ids") String strIds) {
        Assert.isNull(strIds, i18nService.getMessage("DELETE_CONDITION_ILLEGAL"));
        List<Serializable> ids = new ArrayList<>();
        for (String id : strIds.split(SysConstant.SPLIT_REGEX)) {
            if (StringUtils.isNotBlank(id)) {
                ids.add(id);
            }
        }
        User currentUser = SecurityUtils.getLoginUser();
        Assert.isTrue(ids.isEmpty(), i18nService.getMessage("DELETE_CONDITION_ILLEGAL"));
        return R.data(service.deleteUserAndLinked(ids, currentUser));
    }

    @ApiOperation("下载用户数据到excel")
    @PostMapping("downloadExcel")
    @SysLog("下载-用户-数据")
    //@PreAuthorize("hasAuthority('sys:user:downloadExcel')")
    public void downloadExcel(HttpServletResponse response, UserPo params) {
        //获取到查询结果数组
        //List<UserPo> list = service.queryList( params);
        List list = service.queryPage(new QueryModel<>(1, 100000, params)).getRecords();
        //调用导出数据response ：响应, records：导出数据,User.class：导出模板,用户:表名
        ExcelUtils.downLoadExcel(response,list,UserDTO.class,"用户");
    }

    @ApiOperation("下载用户数据到csv")
    @PostMapping("/downloadCsv")
    @SysLog("下载-用户-数据")
    //@PreAuthorize("hasAuthority('sys:user:downloadCsv')")
    public void downloadCsv(HttpServletResponse response, UserPo params) {
        //获取到查询结果数组
        //List<UserPo> list = service.queryList( params);
        List list = service.queryPage(new QueryModel<>(1, 100000, params)).getRecords();
        CsvWriter.downloadCsv(response,list, UserDTO.class,"");
    }

    @ApiOperation("下载数据")
    @PostMapping("downloadTemplate")
    //@SysLog("下载-用户-数据")
    public void downloadTemplate(HttpServletResponse response, UserPo params) {
        //获取到查询结果数组
        //获取到查询结果数组
        List<UserPo> list = service.queryList( params);
        HashMap<Object, Object> fillMap = new HashMap<>(1);
        //数组外的描述可以写这里
        fillMap.put("date","2020-05-26");
        //获取模板地址，也可以前台传模板文件
        String  filePath = getClass().getResource("/template/userTest.xlsx").getPath();
        ExcelUtils.excelTemplateCompositeFill(response,UserDTO.class,list,fillMap,"用户",filePath);
    }

    //@ApiOperation("Excel导入")
    //@PostMapping("uploadExcel")
    //@SysLog("下载-用户-数据")
    public void uploadExcel() throws Exception {
        //1. 读取excel、CSV
        List<Map<String, Object>> maps = ExcelCSVReadUtils.readBySax(new FileInputStream("C:\\Users\\Admin\\Desktop\\t_sys_user.xls"), 0, 1);
        System.out.println(maps);
        //2. 转换结果
        Result result = MapUtil.map2Object(maps, User.class,1);
        System.out.println(result.isCode());
        System.out.println(result.getSize());
        System.out.println(result.getData());
        Object data = result.getData();
        //3. 成功返回true
        if(result.isCode()) {
            //4. 获取对象
            List<User> users = MapUtil.castList(data, User.class);
            for (User user : users) {
                System.out.println(user.getUsername()+"======"+user.getEmail()+"---------"+user.getMobile());
//                ValidatorHelper.validateEntity(user);
                List<String> validate = validate(user);
                validate.forEach(row -> {
                    System.out.println(row.toString());
                });
            }
        }
    }

    //@ApiOperation("CSV导入")
    //@PostMapping("uploadCSV")
    //@SysLog("下载-用户-数据")
    public void uploadCSV() throws Exception {
        List<Map<String, Object>> maps = ExcelCSVReadUtils.readCsv(new FileInputStream("C:\\Users\\Admin\\Desktop\\t_sys_user.csv"), 1, 1);
        System.out.println(maps);


        Result result = MapUtil.map2Object(maps, User.class,1);
        System.out.println(result.isCode());
        System.out.println(result.getSize());
        System.out.println(result.getData());
        Object data = result.getData();
        if(result.isCode()) {
            List<User> users = MapUtil.castList(data, User.class);
            for (User user : users) {
                System.out.println(user.getUsername()+"======"+user.getEmail()+"---------"+user.getMobile());
                ValidatorHelper.validateEntity(user);
                List<String> validate = validate(user);
                validate.forEach(row -> {
                    System.out.println(row.toString());
                });
            }
        }
    }

    private static ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

    public static <T> List<String> validate(T t) {
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);

        List<String> messageList = new ArrayList<>();
        for (ConstraintViolation<T> constraintViolation : constraintViolations) {
            messageList.add(constraintViolation.getMessage());
        }
        return messageList;
    }
}
